home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc / OpenDoc Development / Debugging Support / OpenDoc™ Source Code / UI / WinPopM.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-28  |  22.0 KB  |  838 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        WinPopM.cpp
  3.  
  4.     Contains:    The Document Path pop-up menu
  5.  
  6.     Owned by:    Jens Alfke
  7.  
  8.     Copyright:    © 1994 - 1995 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.          <2>      6/4/96    EL        1335851: Release string from GetEditor.
  13.         <10>     10/4/95    jpa        Fixed ref-count bugs in WalkFrameHierarchy.
  14.                                     [1285639]
  15.          <9>     8/29/95    jpa        Fixes for Univ Hdrs 2.1 & CW7 [1279173]
  16.          <8>     8/25/95    JP        1254840: ODGetIconFamily part to frame
  17.                                     fallout
  18.          <7>     8/16/95    NP        1274946: ErrorDef.idl problems. Add include
  19.                                     file.
  20.          <6>     8/15/95    CC        1275241: Added #include of Aliases.h
  21.          <5>      8/8/95    jpa        Fixed DebugStr [1265584]
  22.          <4>     7/26/95    DM        #1270320: Memory leak fixes: dispose desc
  23.                                     in RevealFinderIcon
  24.          <3>     6/29/95    jpa        Use container ID to get document file spec.
  25.                                     [1261806] Add "Desktop" to pop-up when doc
  26.                                     path ends at desktop. [1262681]
  27.          <2>     6/25/95    TÇ        1242642 BB: Turn on ODDebug warning if
  28.                                     refcount is wrong in
  29.                                     ODRefCntObjectsomUninit.
  30.          <1>     6/19/95    jpa        first checked in
  31.  
  32.     In Progress:
  33.         
  34. */
  35.  
  36.  
  37. #ifndef _WINPOPM_
  38. #include "WinPopM.h"
  39. #endif
  40.  
  41. #ifndef _WINDOW_
  42. #include "Window.xh"
  43. #endif
  44.  
  45. #ifndef _WINSTAT_
  46. #include "WinStat.xh"
  47. #endif
  48.  
  49. #ifndef _DISPTCH_
  50. #include "Disptch.xh"
  51. #endif
  52.  
  53. #ifndef _UIDEFS_
  54. #include "UIDefs.h"
  55. #endif
  56.  
  57. #ifndef _DOCUMENT_
  58. #include <Document.xh>
  59. #endif
  60.  
  61. #ifndef _FRAME_
  62. #include <Frame.xh>
  63. #endif
  64.  
  65. #ifndef _ODCTR_
  66. #include <ODCtr.xh>
  67. #endif
  68.  
  69. #ifndef _ODSTOR_
  70. #include <ODStor.xh>
  71. #endif
  72.  
  73. #ifndef _PARTWRAP_
  74. #include <PartWrap.xh>
  75. #endif
  76.  
  77. #ifndef _LINKMGR_
  78. #include <LinkMgr.xh>
  79. #endif
  80.  
  81. #ifndef _DRAGDRP_
  82. #include <DragDrp.xh>
  83. #endif
  84.  
  85. #ifndef _SHAPE_
  86. #include <Shape.xh>
  87. #endif
  88.  
  89. #ifndef _NMSPCMG_
  90. #include <NmSpcMg.xh>
  91. #endif
  92.  
  93. #ifndef _VALUENS_
  94. #include <ValueNS.xh>
  95. #endif
  96.  
  97. #ifndef _STDDEFS_
  98. #include <StdDefs.xh>
  99. #endif
  100.  
  101. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  102. #include <StdTypes.xh>
  103. #endif
  104.  
  105. #ifndef _BNDNSUTL_
  106. #include <BndNSUtl.h>
  107. #endif
  108.  
  109. #ifndef _INFOUTIL_
  110. #include <InfoUtil.h>
  111. #endif
  112.  
  113. #ifndef _PASCLSTR_
  114. #include <PasclStr.h>
  115. #endif
  116.  
  117. #ifndef _ISOSTR_
  118. #include <ISOStr.h>
  119. #endif
  120.  
  121. #ifndef _PLFMFILE_
  122. #include <PlfmFile.h>
  123. #endif
  124.  
  125. #ifndef _USERSRCM_
  126. #include <UseRsrcM.h>
  127. #endif
  128.  
  129. #ifndef _TEMPOBJ_
  130. #include <TempObj.h>
  131. #endif
  132.  
  133. #ifndef _UTILERRS_
  134. #include "UtilErrs.h"
  135. #endif
  136.  
  137. #ifndef __ERRORS__
  138. #include <Errors.h>
  139. #endif
  140.  
  141. #ifndef __TOOLUTILS__
  142. #include <ToolUtils.h>                    // For BitTst()
  143. #endif
  144.  
  145. #ifndef __ICONS__
  146. #include <Icons.h>
  147. #endif
  148.  
  149. #ifndef __FOLDERS__
  150. #include <Folders.h>
  151. #endif
  152.  
  153. #ifndef __ALIASES__
  154. #include <Aliases.h>
  155. #endif
  156.  
  157. #ifndef __DEVICES__
  158. #include <Devices.h>
  159. #endif
  160.  
  161. #include <stdlib.h>
  162.  
  163. typedef Handle IconSuite;
  164.  
  165.  
  166. const ODSShort kUseSpecificScript = 0x1c;    // Script mgr code for menu items
  167.  
  168. const short kFloppyDriverRefNum = 0xFFFB;    // Floppy (.SONY) driver refnum
  169.  
  170. const Point kMenuOffset = {1,-36};        // Menu offset from window title
  171.  
  172. const short kDefaultDocIconID =   128;    // A default OpenDoc part icon (small sizes only)
  173. const short kPartPopUpMenuID  =  9000;    // Menu ID of title-bar pop-up
  174. const short kGenericPartSICNID=   263;    // SICN ID of generic part icon
  175.  
  176. const  short kKindIconBase = 7;            // Icon# (rsrc ID -256) of 1st reserved icon for parts
  177. const  short kMaxNKindIcons = 5;
  178.  
  179.  
  180. static short gNKindIcons;
  181. static ODType gIconKind[kMaxNKindIcons];
  182.  
  183.  
  184. static short    TitlePopUpSelect( WindowPtr w, const FSSpec &doc, MenuHandle m, Point where );
  185. static ODFrame*     WalkFrameHierarchy( Environment *, ODFrame *, MenuHandle, short stopAtItem =32767 );
  186. static OSErr    RevealFinderIcon( const FSSpec &itemToReveal, const FSSpec &parentFolder );
  187. static    OSErr    GetParentID(short vRefNum,
  188.                             long dirID,
  189.                             StringPtr name,
  190.                             long *parID);
  191. static    OSErr    GetDirName(short vRefNum,
  192.                            long dirID,
  193.                            StringPtr name);
  194. static    OSErr    FSpGetFileLocation(short refNum,
  195.                                    FSSpec *spec);
  196. static ODBoolean VolumeIsFloppy( short vRefNum );
  197.  
  198.  
  199. #pragma segment PathPopUp
  200.  
  201.  
  202. //==============================================================================
  203. #pragma mark    UTILITIES
  204. //==============================================================================
  205.  
  206.  
  207. static ODDocument*
  208. GetDocument( Environment *ev, ODWindow *w )
  209. {
  210.     return w->GetDraft(ev)->GetDocument(ev);
  211. }
  212.  
  213. static void
  214. GetDocumentFileSpec( Environment *ev, ODWindow *w, FSSpec &fss )
  215. {
  216.     TempODContainerIDStruct id(GetDocument(ev,w)->GetContainer(ev)->GetID(ev));
  217.     ASSERT(id->_length>=8 && id->_length<=sizeof(FSSpec), kODErrAssertionFailed);
  218.     ODBlockMove(id->_buffer,&fss,sizeof(FSSpec));
  219. }
  220.  
  221. static ODSession*
  222. GetSession( Environment *ev, ODDocument *document )
  223. {
  224.     return document->GetContainer(ev)->GetStorageSystem(ev)->GetSession(ev);
  225. }
  226.  
  227. static ODSession*
  228. GetSession( Environment *ev, ODWindow *window )
  229. {
  230.     return GetSession(ev,GetDocument(ev,window));
  231. }
  232.  
  233. static ODSession*
  234. GetSession( Environment *ev, ODPersistentObject *po )
  235. {
  236.     return po->GetStorageUnit(ev)->GetSession(ev);
  237. }
  238.  
  239.  
  240. //==============================================================================
  241. #pragma mark    TITLE-BAR CLICKS
  242. //==============================================================================
  243.  
  244.  
  245.    /////////////////////////////////////////////////////////////
  246.   //    TrackWindowPathPopUp                                 //
  247.  //            Called from any click in title bar                //
  248. /////////////////////////////////////////////////////////////
  249. ODBoolean
  250. TrackWindowPathPopUp( Environment *ev, ODWindow *w, Point where )
  251. {
  252.     KeyMap keys;
  253.     GetKeys(keys);
  254.     
  255.     if( ! BitTst(&keys,0x30) )                        // Must be holding down Command key
  256.         return kODFalse;
  257.         
  258.     WindowPtr wp = w->GetPlatformWindow(ev);
  259.     if( !((WindowPeek)wp)->hilited )
  260.         return kODFalse;                            // Window must be active
  261.     
  262.     if( w->IsFloating(ev) || !w->GetDraft(ev) )        // Must not be floating window
  263.         return kODFalse;                            // and must have a draft
  264.         
  265.     ODFrame *frame = w->GetRootFrame(ev);            // Must have an OpenDoc frame
  266.     if( !frame )
  267.         return kODFalse;
  268.         
  269.     Str255 title;
  270.     GetWTitle(wp,title);
  271.     SetPort(LMGetWMgrPort());
  272.     short titleWidth = StringWidth(title);
  273.     SetPort(wp);
  274.     GlobalToLocal(&where);
  275.     
  276.     if( abs(where.h-(wp->portRect.right-wp->portRect.left)/2) <= titleWidth/2 ) {
  277.     
  278.         // Where does the pop-up go?
  279.         Point popWhere;
  280.         popWhere.h = (wp->portRect.left+wp->portRect.right-titleWidth)/2 + kMenuOffset.h;
  281.         LocalToGlobal(&popWhere);
  282.         popWhere.v = (**((WindowPeek)wp)->strucRgn).rgnBBox.top + kMenuOffset.v;
  283.     
  284.         CUsingLibraryResources u;
  285.         
  286.         // Build the pop-up:
  287.         MenuHandle m = NewMenu(kPartPopUpMenuID,"\p");
  288.         if( !m ) return kODTrue;
  289.         ODFrame *f1 = WalkFrameHierarchy(ev,frame,m);
  290.         ODReleaseObject(ev,f1);
  291.         
  292.         // Pop it up:
  293.         FSSpec fss;
  294.         GetDocumentFileSpec(ev,w,fss);
  295.         short item= TitlePopUpSelect(wp, fss, m, popWhere);
  296.         
  297.         // If user selected a parent frame, show its window & select the frame:
  298.         if( item>1 && item<=CountMItems(m) ) {
  299.             TempODFrame f2 = WalkFrameHierarchy(ev,frame,kODNULL,item);
  300.             TempODWindow w = f2->AcquireWindow(ev);
  301.             w->Select(ev);
  302.         }
  303.         
  304.         DisposeMenu(m);
  305.         return kODTrue;
  306.         
  307.     } else
  308.         return kODFalse;
  309. }
  310.  
  311.  
  312. //==============================================================================
  313. #pragma mark    BUILDING THE POP-UP
  314. //==============================================================================
  315.  
  316.  
  317. inline void
  318. ClearPartMenuIcons( )
  319. {
  320.     gNKindIcons = 1;
  321.     gIconKind[0] = kODNULL;        // Reserve one icon as a default
  322. }
  323.  
  324.  
  325.    /////////////////////////////////////////////////////////////
  326.   //    GetPartMenuIcon                                         //
  327.  //            Return an icon ID to use for a part                //
  328. /////////////////////////////////////////////////////////////
  329. static short
  330. GetPartMenuIcon( Environment *ev, ODFrame *frame )
  331. {
  332.     TempODPart    part = frame->AcquirePart(ev);
  333.     ODType        kind = ODGetKind(ev, part);
  334.     short i;
  335.     for( i=0; i<gNKindIcons; i++ )
  336.         if( gIconKind[i]==kind || ODISOStrEqual(gIconKind[i],kind) )
  337.             return kKindIconBase+i;                        // Already have an icon
  338.     if( gNKindIcons==kMaxNKindIcons )
  339.         return kKindIconBase+0;                            // Default icon
  340.     else {
  341.         gIconKind[gNKindIcons++] = kind;                // Remember a new kind
  342.         
  343.         // A slightly sick way to customize the icon in the pop-up.
  344.         // Get the SICN and copy the appropriate 'ics#' data into it in memory.
  345.         // Since the resource is never written back to disk, and the resource
  346.         // file will be closing right afterwards, this is safe to do:
  347.         IconSuite partIconSuite = ODGetIconFamily(ev, frame);
  348.         if( partIconSuite ) {
  349.             Handle icon;
  350.             (void) GetIconFromSuite(&icon, partIconSuite, 'ics#');
  351.             if( icon ) {
  352.                 Handle sicn = Get1Resource('SICN',256+kKindIconBase+i);
  353.                 if( sicn )
  354.                     ODBlockMove(*icon,*sicn,GetHandleSize(sicn));
  355.             }
  356.             DisposeIconSuite(partIconSuite,true);
  357.         }
  358.         return kKindIconBase+i;
  359.     }
  360. }
  361.  
  362.  
  363.    /////////////////////////////////////////////////////////////
  364.   //    GetNameForPart                                         //
  365.  //            Create an IText with a name for this part        //
  366. /////////////////////////////////////////////////////////////
  367. static ODIText*
  368. GetNameForPart( Environment *ev, ODPart *part )
  369. {
  370.     // Come up with something to call the part: either its real name,
  371.     // its editor name, or at last resort its SOM class name.
  372.     
  373.     ODIText* partName = ODGetPOName(ev, part, kODNULL);
  374.     if( partName )
  375.         return partName;
  376.  
  377.     // Part itself has no name, so use editor name:
  378.     TempODEditor editorID = ((ODPartWrapper*)part)->GetEditor(ev);
  379.     if( GetUserEditorFromEditor(GetSession(ev,part)->GetNameSpaceManager(ev), editorID, &partName) )
  380.         return CopyIText(partName);
  381.  
  382.     // Could not get editor name, resort to SOM classname:
  383.     char *namePtr = editorID;
  384.     char *lastcolon = strrchr(namePtr,':');
  385.     if( lastcolon )
  386.         namePtr = lastcolon+1;        // Use last segment of name
  387.     return CreateITextCString(smRoman,langEnglish,namePtr);
  388. }
  389.  
  390.  
  391.    /////////////////////////////////////////////////////////////
  392.   //    WalkFrameHierarchy                                     //
  393.  //            Make the frame-hierarchy pop-up menu            //
  394. /////////////////////////////////////////////////////////////
  395. static ODFrame*
  396. WalkFrameHierarchy( Environment *ev, ODFrame *startFrame, MenuHandle m, short stopAtItem )
  397. {
  398.     /*    This has two purposes. (1) it builds the initial pop-up menu for the title-bar.
  399.         The HFS path of the document will be appended to this before the user sees it.
  400.         (2) If the user chooses one of the items added to the menu by this routine,
  401.         it's called again, with no menu but stopAtItem set, to determine which frame
  402.         corresponded to that item.
  403.         ** You must release the frame returned by this function **
  404.     */
  405.     
  406.     ClearPartMenuIcons();
  407.     
  408.     startFrame->Acquire(ev);                    // It will be released later
  409.     TempODFrame frame = startFrame;                // Reference to current frame, on our walk
  410.     TempODFrame parent = kODNULL;                // Reference to its parent frame
  411.     
  412.     while( frame ) {
  413.         if( --stopAtItem <= 0 )
  414.             break;
  415.         
  416.         // Find the parent frame, going to the parent window if necessary:
  417.         {
  418.             TempODWindow frameWindow = kODNULL;
  419.             parent = frame->AcquireContainingFrame(ev);
  420.             
  421.             if( !parent ) {
  422.                 frameWindow = frame->AcquireWindow(ev);
  423.                 parent = frameWindow->AcquireSourceFrame(ev);
  424.                 if( parent ) {
  425.                     ODFrame *parent2 = parent->AcquireContainingFrame(ev);  // -- TÇ: swapping refcounts here
  426.                     parent->Release(ev);                                     // -- TÇ: swapping refcounts here
  427.                     parent = parent2;
  428.                 }
  429.             }
  430.             
  431.             if( m ) {
  432.                 // Add menu item for this frame:
  433.                 TempODPart part = frame->AcquirePart(ev);
  434.                 Str255 nameStr;
  435.                 
  436.                 AppendMenu(m,"\pX");
  437.                 short mItem = CountMItems(m);
  438.                 SetItemIcon(m,mItem,GetPartMenuIcon(ev, frame));
  439.                 SetItemCmd(m,mItem,0x1E);
  440.     
  441.                 if( frameWindow )                                // Use window title if possible
  442.                     GetWTitle(frameWindow->GetPlatformWindow(ev),nameStr);
  443.                 else
  444.                     nameStr[0] = 0;
  445.                     
  446.                 if( nameStr[0] == 0 ) {
  447.                     ODIText *t = GetNameForPart(ev,part);        // Else use part's name
  448.                     if( t ) {
  449.                         GetITextPString(t,nameStr);
  450.                         short s = GetITextScriptCode(t);
  451.                         if( s != GetScriptManagerVariable(smSysScript) ) {
  452.                             SetItemCmd(m, mItem, kUseSpecificScript);    // Force script
  453.                             SetItemIcon(m, mItem, s);
  454.                         }
  455.                         DisposeIText(t);
  456.                     }
  457.                 }
  458.                 SetMenuItemText(m,mItem,nameStr);
  459.             }
  460.             
  461.             frame.Release();        // Forget current frame,
  462.             frame = (ODFrame*)parent;            // switch to parent
  463.             parent = kODNULL;
  464.         }
  465.     }
  466.     
  467.     return frame.DontRelease();        // Return frame, don't release it (caller must do so)
  468. }
  469.  
  470.  
  471. /*=======================================================================================*/
  472. #pragma mark    TITLE POP-UP
  473. /*=======================================================================================*/
  474.  
  475.  
  476. const short kTitlePopUpMenuID = 30000;        // Created on the fly
  477. const long kRootDir = 2;
  478.  
  479. // 'SICN' resource IDs for the icons in the path menu.
  480. // BuildPathMenu assumes these icons are in the resource chain and not overridden
  481. // by any other icons.
  482. enum {
  483.     kDocumentSICN = 257, /*unused*/
  484.     kFolderSICN,
  485.     kTrashSICN,    /*unused*/
  486.     kDiskSICN,
  487.     kFloppySICN,
  488.     kDesktopSICN
  489. };
  490.  
  491.  
  492.    /////////////////////////////////////////////////////////////
  493.   //    BuildPathMenu                                         //
  494.  //            Make the pop-up menu for the HFS path             //
  495. /////////////////////////////////////////////////////////////
  496. static void
  497. BuildPathMenu( FSSpec *spec, MenuHandle m, short stopAtItem )
  498. {
  499.     // This routine assumes that spec is a file, not a directory.
  500.     
  501.     stopAtItem++;
  502.     
  503.     short vol = spec->vRefNum;
  504.     long  dir = 0;
  505.     
  506.     long desktopDir;
  507.     short foundVol;
  508.     THROW_IF_ERROR( FindFolder(vol,kDesktopFolderType, true, &foundVol,&desktopDir) );
  509.     
  510.     for( short item=1; item<stopAtItem; item++ ) {
  511.         // Get the name of the current' item's parent dir, and the parent ID of that:
  512.         long parent;
  513.         dir = spec->parID;
  514.         if( GetParentID(vol,spec->parID,NULL, &parent) != noErr )    // Get next parent
  515.             break;
  516.         if( GetDirName(vol,spec->parID, spec->name) != noErr )        // Get name of current parent
  517.             break;
  518.         spec->parID = parent;
  519.  
  520.         // Add the current item to the menu:
  521.         if( m ) {
  522.             AppendMenu(m,"\pX");                    // Two steps in case...
  523.             short mItem = CountMItems(m);
  524.             if( dir==desktopDir )
  525.                 ODGetString(spec->name,kODDesktopTitleStrID);
  526.             SetMenuItemText(m,mItem,spec->name);    // ...spec->name contains meta-chars
  527.             short icon;
  528.             if( dir==desktopDir )
  529.                 icon = kDesktopSICN - 256;
  530.             else if( dir!=kRootDir )
  531.                 icon = kFolderSICN - 256;
  532.             else if( VolumeIsFloppy(vol) )
  533.                 icon = kFloppySICN - 256;
  534.             else
  535.                 icon = kDiskSICN - 256;
  536.             SetItemIcon(m,mItem,icon);
  537.             SetItemCmd(m,mItem,0x1E);
  538.         }
  539.         
  540.         // Quit when we reach the desktop or volume root:
  541.         if( dir==desktopDir || dir==kRootDir )
  542.             break;
  543.     }
  544. }
  545.  
  546.  
  547.    /////////////////////////////////////////////////////////////
  548.   //    TitlePopUpSelect                                     //
  549.  //            Big kahuna that runs the pop-up                    //
  550. /////////////////////////////////////////////////////////////
  551. static short
  552. TitlePopUpSelect( WindowPtr w, const FSSpec &doc, MenuHandle m, Point where )
  553. {
  554.     short prevItems = CountMItems(m);
  555.     FSSpec itemSpec = doc;
  556.     
  557.     BuildPathMenu(&itemSpec,m,32000);                            // Append path to file to the menu
  558.     
  559.     InsertMenu(m,-1);
  560.     short item= (short) PopUpMenuSelect(m,where.v,where.h, 1);        // Shazam! Pop up the menu
  561.     DeleteMenu((**m).menuID);
  562.     
  563.     for( short count = CountMItems(m); count>prevItems; count-- )    // Restore to prev state
  564.         DeleteMenuItem(m,count);
  565.     
  566.     if( item > prevItems && item>1 ) {                        // Item 1 is just the document itself
  567.         FSSpec parentSpec = doc;
  568.         BuildPathMenu(&parentSpec,NULL,item-prevItems);        // Folder to open
  569.         itemSpec = doc;
  570.         BuildPathMenu(&itemSpec,NULL,item-prevItems-1);        // Item in folder to reveal
  571.         OSErr err = RevealFinderIcon(itemSpec,parentSpec);    // Tell the Finder to reveal it
  572.     }
  573.     return item;
  574. }
  575.  
  576.  
  577. /*============================================================================================*/
  578. #pragma mark    TALKING TO THE FINDER
  579. /*============================================================================================*/
  580.  
  581.  
  582. #define kFinderSignature    'MACS'
  583. #define kFinderEventClass    'FNDR'
  584. #define kFinderRevealEvent    'srev'
  585. #define keyFinderSelection    'fsel'
  586.  
  587.  
  588.    /////////////////////////////////////////////////////////////
  589.   //    CreateFinderRevealEvent                                 //
  590.  //            Build an AEvt for revealing an item                //
  591. /////////////////////////////////////////////////////////////
  592. static OSErr
  593. CreateFinderRevealEvent( const FSSpec *itemToReveal, const FSSpec *parentFolder, AEDesc *evt )
  594. {
  595.     OSErr err;
  596.     OSType finderSignature = kFinderSignature;
  597.     AliasHandle alias = NULL;
  598.     AEDesc target = {typeNull,NULL};
  599.     AEDescList list = {typeNull,NULL};
  600.     
  601.     evt->dataHandle = NULL;
  602.     
  603.     err= AECreateDesc(typeApplSignature,&finderSignature,sizeof(OSType), &target);
  604.     if( err ) goto exit;
  605.     err= AECreateAppleEvent(kFinderEventClass, kFinderRevealEvent,
  606.                             &target, kAutoGenerateReturnID, kAnyTransactionID,
  607.                             evt);
  608.     if( err ) goto exit;
  609.     AEDisposeDesc(&target);
  610.     
  611.     err= NewAlias(NULL,parentFolder,&alias);            // Parent folder param must be full alias
  612.     if( err ) goto exit;
  613.     HLockHi((Handle)alias);
  614.     err= AEPutParamPtr(evt,keyDirectObject, typeAlias,*alias,GetHandleSize((Handle)alias));
  615.     DisposeHandle((Handle)alias);
  616.     alias = NULL;
  617.     
  618.     err= NewAliasMinimal(itemToReveal,&alias);
  619.     if( err ) goto exit;
  620.  
  621.     err= AECreateList(NULL,0,false, &list);
  622.     if( err ) goto exit;
  623.     err= AEPutPtr(&list,1,typeAlias,*alias,GetHandleSize((Handle)alias));
  624.     if( err ) goto exit;
  625.     
  626.     err= AEPutParamDesc(evt,keyFinderSelection, &list);
  627.     if( err ) goto exit;
  628.  
  629. exit:
  630.     AEDisposeDesc(&target);
  631.     AEDisposeDesc(&list);
  632.     if( alias ) DisposeHandle((Handle)alias);
  633.     if( err )
  634.         AEDisposeDesc(evt);
  635.     
  636.     return err;
  637. }
  638.  
  639.  
  640.    /////////////////////////////////////////////////////////////
  641.   //    ActivateFinder                                         //
  642.  //            Make the Finder the front process                //
  643. /////////////////////////////////////////////////////////////
  644. static void
  645. ActivateFinder( )
  646. {
  647.     OSErr err;
  648.     ProcessSerialNumber process = {0,kNoProcess};
  649.     for(;;) {
  650.         err= GetNextProcess(&process);
  651.         if( err )
  652.             break;
  653.         ProcessInfoRec info;
  654.         info.processInfoLength = sizeof(info);
  655.         info.processName = NULL;
  656.         info.processAppSpec = NULL;
  657.         err= GetProcessInformation(&process,&info);
  658.         if( err )
  659.             break;
  660.         if( info.processSignature == kFinderSignature ) {
  661.             err= SetFrontProcess(&process);
  662.             if( err )
  663.                 break;
  664.             else
  665.                 return;
  666.         }
  667.     }
  668.     WARN("Couldn't activate Finder!");
  669. }
  670.  
  671.  
  672.    /////////////////////////////////////////////////////////////
  673.   //    RevealFinderIcon                                     //
  674.  //            Send the Finder an AEvt for revealing an item    //
  675. /////////////////////////////////////////////////////////////
  676. static OSErr
  677. RevealFinderIcon( const FSSpec &itemToReveal, const FSSpec &parentFolder )
  678. {
  679.     OSErr err;
  680.     AppleEvent evt, reply;
  681.     
  682.     err= CreateFinderRevealEvent(&itemToReveal,&parentFolder, &evt);
  683.     TempAEDesc tempErr(&evt); // make sure it is disposed
  684.     if( !err )
  685.         err= AESend(&evt,&reply, kAENoReply|kAEAlwaysInteract|kAECanSwitchLayer,
  686.                     kAENormalPriority, kNoTimeOut, NULL,NULL);
  687.     if( !err )
  688.         ActivateFinder();
  689.     return err;
  690. }
  691.  
  692.  
  693. /*============================================================================================*/
  694. #pragma mark    SWIPED FROM MOREFILES 1.2.1
  695. /*============================================================================================*/
  696.  
  697.  
  698. static    OSErr    GetParentID(short vRefNum,
  699.                             long dirID,
  700.                             StringPtr name,
  701.                             long *parID)
  702. {
  703.     CInfoPBRec pb;
  704.     OSErr error;
  705.     
  706.     pb.hFileInfo.ioNamePtr = name;
  707.     pb.hFileInfo.ioVRefNum = vRefNum;
  708.     pb.hFileInfo.ioDirID = dirID;
  709.     pb.hFileInfo.ioFDirIndex = name ?0 :-1;
  710.     error = PBGetCatInfoSync(&pb);
  711.     *parID = pb.hFileInfo.ioFlParID;
  712.     return ( error );
  713. }
  714.  
  715.  
  716. static    OSErr    GetDirName(short vRefNum,
  717.                            long dirID,
  718.                            StringPtr name)
  719.         {
  720.     CInfoPBRec pb;
  721.  
  722.     pb.hFileInfo.ioNamePtr = name;
  723.     pb.hFileInfo.ioVRefNum = vRefNum;
  724.     pb.hFileInfo.ioDirID = dirID;
  725.     pb.hFileInfo.ioFDirIndex = -1;    /* get information about ioDirID */
  726.     return ( PBGetCatInfoSync(&pb) );
  727. }
  728.  
  729.  
  730. static    OSErr    GetFileLocation(short refNum,
  731.                                 short *vRefNum,
  732.                                 long *dirID,
  733.                                 StringPtr fileName)
  734. {
  735.     FCBPBRec pb;
  736.     OSErr error;
  737.  
  738.     pb.ioNamePtr = fileName;
  739.     pb.ioVRefNum = 0;
  740.     pb.ioRefNum = refNum;
  741.     pb.ioFCBIndx = 0;
  742.     error = PBGetFCBInfoSync(&pb);
  743.     *vRefNum = pb.ioFCBVRefNum;
  744.     *dirID = pb.ioFCBParID;
  745.     return ( error );
  746. }
  747.  
  748.  
  749. static    OSErr    FSpGetFileLocation(short refNum,
  750.                                    FSSpec *spec)
  751. {
  752.     return ( GetFileLocation(refNum, &(spec->vRefNum), &(spec->parID), spec->name) );
  753. }
  754.  
  755.  
  756. static    OSErr    FindDrive(StringPtr pathname,
  757.                           short vRefNum,
  758.                           DrvQElPtr *driveQElementPtr)
  759. {
  760.     OSErr            result;
  761.     Str255            tempPathname;
  762.     HParamBlockRec    hPB;
  763.     short            driveNumber;
  764.     
  765.     *driveQElementPtr = NULL;
  766.     
  767.     /* First, use PBHGetVInfo to determine the volume */
  768.     hPB.volumeParam.ioVRefNum = vRefNum;
  769.     if ( pathname == NULL )
  770.     {
  771.         hPB.volumeParam.ioNamePtr = NULL;
  772.         hPB.volumeParam.ioVolIndex = 0;    /* use ioVRefNum only */
  773.     }
  774.     else
  775.     {
  776.         ODBlockMove(pathname, tempPathname, pathname[0] + 1);    /* make a copy of the string and */
  777.         hPB.volumeParam.ioNamePtr = (StringPtr)tempPathname;    /* use the copy so original isn't trashed */
  778.         hPB.volumeParam.ioVolIndex = -1;    /* use ioNamePtr/ioVRefNum combination */
  779.     }
  780.     result = PBHGetVInfoSync(&hPB);
  781.     if ( result == noErr )
  782.     {
  783.         /*
  784.         **    The volume can be either online, offline, or ejected. What we find in
  785.         **    ioVDrvInfo and ioVDRefNum will tell us which it is.
  786.         **    See Inside Macintosh: Files page 2-80 and the Technical Note
  787.         **    "FL 34 - VCBs and Drive Numbers : The Real Story"
  788.         **    Where we get the drive number depends on the state of the volume.
  789.         */
  790.         if ( hPB.volumeParam.ioVDrvInfo != 0 )
  791.         {
  792.             /* The volume is online and not ejected */
  793.             /* Get the drive number */
  794.             driveNumber = hPB.volumeParam.ioVDrvInfo;
  795.         }
  796.         else
  797.         {
  798.             /* The volume's is either offline or ejected */
  799.             /* in either case, the volume is NOT online */
  800.  
  801.             /* Is it ejected or just offline? */
  802.             if ( hPB.volumeParam.ioVDRefNum > 0 )
  803.             {
  804.                 /* It's ejected, the drive number is ioVDRefNum */
  805.                 driveNumber = hPB.volumeParam.ioVDRefNum;
  806.             }
  807.             else
  808.             {
  809.                 /* It's offline, the drive number is the negative of ioVDRefNum */
  810.                 driveNumber = (short)-hPB.volumeParam.ioVDRefNum;
  811.             }
  812.         }
  813.         
  814.         /* Get pointer to first element in drive queue */
  815.         *driveQElementPtr = (DrvQElPtr)(GetDrvQHdr()->qHead);
  816.         
  817.         /* Search for a matching drive number */
  818.         while ( (*driveQElementPtr != NULL) && ((*driveQElementPtr)->dQDrive != driveNumber) )
  819.         {
  820.             *driveQElementPtr = (DrvQElPtr)(*driveQElementPtr)->qLink;
  821.         }
  822.         
  823.         if ( *driveQElementPtr == NULL )
  824.         {
  825.             /* This should never happen since every volume must have a drive, but... */
  826.             result = nsDrvErr;
  827.         }
  828.     }
  829.     
  830.     return ( result );
  831. }
  832.  
  833. static ODBoolean VolumeIsFloppy( short vRefNum )
  834. {
  835.     DrvQElPtr q;
  836.     return FindDrive(NULL,vRefNum,&q)==noErr && q->dQRefNum==kFloppyDriverRefNum;
  837. }
  838.